package com.yuanfud.zuulServer.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.yuanfud.common.exception.ErrorInfo;
import com.yuanfud.common.util.ErrorCode;
import com.yuanfud.common.util.IPUtil;
import com.yuanfud.common.util.JwtHandler;
import org.apache.commons.lang.StringUtils;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.lang.JoseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.Request;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.LinkedHashMap;
import java.util.Map;

public class TokenHandlerFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(TokenHandlerFilter.class);

    private static final String[] IGNORE_URI = {"login","news","password","website"};

    @Override
    public String filterType()
    {
        return "pre";
    }

    @Override
    public int filterOrder()
    {
        return 0;
    }

    @Override
    public boolean shouldFilter()
    {
        RequestContext ctx = RequestContext.getCurrentContext();
        log.info(ctx.getRequest().getRequestURI() + " get request path info");
        String url = ctx.getRequest().getRequestURI().toLowerCase();
        if (!StringUtils.isEmpty(url)) {
            for (String loginurl : IGNORE_URI) {
                if (url.contains(loginurl)) {
                    ctx.set("isSuccess", false);
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public Object run()
    {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        ctx.getResponse().setCharacterEncoding("UTF-8");

        log.info("the request host ip is:"+ request.getRemoteHost()+":"+request.getRemoteAddr());
        log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        //判断token是否为null
        String accessToken = request.getHeader("Authorization");
        if(StringUtils.isEmpty(accessToken)) {
            log.info("access token is empty");
            errorFunction(ctx,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR_MSG);
            ctx.set("isSuccess", false);
            return null;
        }

        //AppKey的判断
        String appKey = request.getHeader("appkey");

        if(appKey == null || appKey.length() <=0){
            log.info("access token is empty");
            errorFunction(ctx,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR_MSG);
            ctx.set("isSuccess", false);
            return null;
        }

        //是否重复请求


        Map<String, Object> claims = new LinkedHashMap<String, Object>();

        try
        {
            claims = JwtHandler.claimsOfToken(accessToken);

            //验证IP
            String addrIp = IPUtil.getIpAddr(request);

            log.info("the addrIp is:" + addrIp);
            log.info("the claimsip is:" + claims.get("ip"));
            String claimsIp = (String) claims.get("ip");
            if(!claimsIp.contains(addrIp)){
                //Token 错误
                errorFunction(ctx,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR_MSG);
                ctx.set("isSuccess", false);
                return null;
            }

            //token 过期判断



        } catch (JoseException e)
        {
            //Token 错误
            errorFunction(ctx,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR,ErrorCode.ZUUL_TOKEN_VALIDATE_NULL_ERROR_MSG);
            ctx.set("isSuccess", false);
            return null;
        }

        //验证token，包括token是否有效，有效期，以及IP的请求是否合法
        try
        {
            JwtHandler.volatileToken(accessToken,(String)claims.get("sub"));
        } catch (JoseException e)
        {
            log.info("hhhhhhhhhhhhhh"+e.getMessage());
            //Token 错误
            errorFunction(ctx,ErrorCode.ZUUL_TOKEN_VALIDATE_NOT_NORMAL_ERROR,ErrorCode.ZUUL_TOKEN_VALIDATE_NOT_NORMAL_ERROR_MSG);
            ctx.set("isSuccess", false);
            return null;

        } catch (InvalidJwtException e)
        {
            log.info("ddddddddddddd"+e.getMessage());
            //Token 错误
            errorFunction(ctx,ErrorCode.ZUUL_TOKEN_VALIDATE_NOT_NORMAL_ERROR,ErrorCode.ZUUL_TOKEN_VALIDATE_NOT_NORMAL_ERROR_MSG);
            ctx.set("isSuccess", false);
            return null;
        }

        ctx.addZuulRequestHeader("Id",String.valueOf(claims.get("Id")));
        ctx.addZuulRequestHeader("userName",(String)claims.get("userName"));
        ctx.addZuulRequestHeader("loginId",String.valueOf(claims.get("loginId")));
//        ctx.addZuulRequestHeader("chanId",(String) claims.get("chanId"));
//        ctx.addZuulRequestHeader("chanName",(String) claims.get("chanName"));

        ctx.set("isSuccess", true);
        log.info("access token ok");
        return null;
    }

    public static void  errorFunction(RequestContext ctx, int code, String message){
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(401);

        ErrorInfo errorInfo = new ErrorInfo();
        errorInfo.setCode(code);
        errorInfo.setMessage(message);

        ctx.setResponseBody(errorInfo.toString());
    }

}